#include "state.h"
#include <string.h>

#define UM_OK               (0)
#define UM_FULL             (1)
#define UM_EMPTY            (2)

typedef struct
{
	u8          front;          //head
	u8          rear;           //tail
	MSG         value[MQ_SIZE];
}MQ;

static MQ _q = {0};

//============================================================
u8 MQ_Push(MSG msg)
{
	u8 next_rear = (_q.rear + 1) % MQ_SIZE;
	if (  next_rear == _q.front )
	{
		return UM_FULL;
	}
	else
	{
		memcpy(&_q.value[_q.rear],&msg,sizeof(MSG));
		_q.rear = next_rear;
	}
	return UM_OK;
}

u8 MQ_Pop(MSG  *p_msg)
{
    if (_q.rear == _q.front)
    {
        return UM_EMPTY;
    }
    else
    {
    	memcpy(p_msg,&_q.value[_q.front],sizeof(MSG));
    	memset(&_q.value[_q.front],0,sizeof(MSG));
        _q.front = (_q.front+1) % MQ_SIZE;
    }
    return UM_OK;
}

//----------------------------------------------------------------
void GetMessage(MSG *p_msg)
{
	if ( MQ_Pop(p_msg) == UM_EMPTY )
	{
		memset(p_msg,0,sizeof(MSG));
	}
}

void PostMessage(u8 message,u32 param)
{
	MSG msg;
	msg.message = message;
	msg.param = param;
	MQ_Push(msg);
}

//--------------------------------------------
State st;

void State_Init(void)
{
    _q.front = 0;
    _q.rear = 0;

    st = 0;
}

void State_Change(State NewState)
{
	st = NewState;
	PostMessage(WM_STATE_ENTER,(u32)NewState);
}


void State_Exec(void)
{
	MSG msg = {0,0};
	GetMessage(&msg);
	if ( msg.message == WM_STATE_ENTER )
	{
		if ( msg.param )
		{
		    ((State)(msg.param))(&msg);
		}
	}
	else if ( msg.message != WM_NULL )
	{
		if ( st )
		{
            (st)(&msg);
		}
	}
}
